package com.util;

import android.annotation.SuppressLint;
import android.os.AsyncTask;
import android.text.TextUtils;
import android.util.Base64;

import com.constant.Constant;
import com.interfaces.IShortSocket;
import com.socket.UnPacket;

import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;

/**
 * Created by Mars on 2017/9/25.
 */

@SuppressLint("NewApi")
public class SocketTask extends AsyncTask<String, Void, String> {

    private IShortSocket iShortSocket;
    private ByteBuffer byteBuffer = ByteBuffer.allocateDirect(1024);
    private static Socket socket;
    private static String ip;
    private static int port;
    private static int TIMEOUT = 12000;
    private static InputStream is;
    private static OutputStream os;
    private boolean flag;
    private int mLength;
    private String mJson;
    private short mType;                 //包类型
    private short packageOrderNum;       //包序号
    private String mBody;                //包体

    public SocketTask(String ip, int port, short type, short packageOrderNum, String body, IShortSocket iShortSocket) {
        this.ip = ip;
        this.port = port;
        this.mType = type;
        this.packageOrderNum = packageOrderNum;
        this.mBody = body;
        this.iShortSocket = iShortSocket;
        LogUtil.e("SocketTask : Create");
    }

    public static Socket getInstance() {
        if (socket == null) {
            socket = new Socket();
        }
        return socket;
    }

    public SocketTask(short type, String body, IShortSocket iShortSocket) {
        this.ip = Constant.IP;
        this.port = Constant.PORT;
        this.mType = type;
        this.packageOrderNum = 0;
        this.mBody = body;
        this.iShortSocket = iShortSocket;
        LogUtil.e("SocketTask : Create");
    }

    private String connect() {
        String message = "";
        try {
            byteBuffer.order(ByteOrder.nativeOrder());
            socket = new Socket();
            InetSocketAddress address = new InetSocketAddress(ip, port);
            socket.connect(address, TIMEOUT);
            os = socket.getOutputStream();
            is = socket.getInputStream();
            LogUtil.e(":  --connect-success");
            sendData(os, mType, packageOrderNum, mBody);
            received(is);
        } catch (UnknownHostException e) {
            message = "UnknownHostException";
        } catch (IOException e) {
            message = "IOException";
        }

        return message;
    }

    private void received(InputStream is) throws IOException {
        byte[] buffer = new byte[1024];
        int length;
        try {
            while (!flag && (length = is.read(buffer)) != -1) {
                flag = getData(buffer, length);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

//        handing(is);
    }


    private DataInputStream dis;
    private byte[] head = new byte[8];
    private int headLen = 0;

    private void handing(InputStream is) {
        while (true) {
            try {//获取包头数据
                int len = is.read(head, headLen, 8 - headLen);
                //判断包头数据是否完整
                headLen += len;//记录包头长度
                if (headLen == 8) {
                    int packetLen = head[1] << 8 | head[0];
                    System.out.println("包长度:" + packetLen);
                    headLen = 0;

                    //读取包体数据
                    byte[] body = new byte[packetLen];
                    int bodyLen = 0;
                    while (true) {
                        int recBodyLen = is.read(body, bodyLen, packetLen - bodyLen - 8);
                        bodyLen += recBodyLen;
                        //得到完整包
                        if (bodyLen == (packetLen - 8)) {
                            //解析数据
                            UnPacket unPacket = new UnPacket(head, body);
                            unPacket.Parser();
                            break;
                        }
                    }
                } else {
                    System.out.println("包头不够继续接收");
                }
            } catch (IOException e) {
                break;
            }
        }

    }

    private boolean getData(byte[] buffer, int length) throws IOException {
        byteBuffer.put(buffer, 0, length);
        byteBuffer.position(0);
        mLength += length;
        if (mLength >= 8) {
            short packageSize = byteBuffer.getShort();
            short packageInstruction = byteBuffer.getShort();
            short packageType = byteBuffer.getShort();
            short packageOrderNum = byteBuffer.getShort();
            LogUtil.e("packageOrderNum = " + packageOrderNum);
            short bodySize = (short) (packageSize - 8);
            if (bodySize + 8 <= mLength) {
                byte[] body = new byte[bodySize];
                byteBuffer.get(body);
                byte[] decode = Base64.decode(body, Base64.DEFAULT);
                mJson = new String(decode);
                // shortSocketListener.getData(json);
//                is.close();
//                os.close();
                LogUtil.e("received-json:" + mJson);
                return true;
            }
        }
        return false;
    }

    public void sendData(OutputStream os, short type, short msgId, String body) throws IOException {
        int length = 8 + body.length();
        byte[] msg = new byte[length];
        byte[] temp;
        temp = DataTypeUtil.short2byte((short) length);//长度
        System.arraycopy(temp, 0, msg, 0, 2);
        temp = DataTypeUtil.short2byte(Constant.TYPE_INSTRUCTION);//包的指令类型
        System.arraycopy(temp, 0, msg, 2, 2);
        temp = DataTypeUtil.short2byte(type);// 包类型
        System.arraycopy(temp, 0, msg, 4, 2);
        temp = DataTypeUtil.short2byte(msgId);// 包序号
        System.arraycopy(temp, 0, msg, 6, 2);
        temp = body.getBytes();
        System.arraycopy(temp, 0, msg, 8, body.length());
        os.write(msg, 0, msg.length);
    }

    @Override
    protected void onPostExecute(String result) {
        if (TextUtils.isEmpty(result)) {
            if (!TextUtils.isEmpty(mJson))
                iShortSocket.getData(mJson);
            else
                iShortSocket.getDataError();
        } else iShortSocket.connectError();
    }

    @Override
    protected String doInBackground(String... strings) {
        LogUtil.e("doInBackground");
        String result = connect();

        if (TextUtils.isEmpty(mJson)) {
            result = connect();
        }
        return result;
    }

    public static OutputStream getOS() {
        if (os == null) {
            try {
                if (socket == null || !socket.isConnected()) {
                    socket = new Socket();
                    InetSocketAddress address = new InetSocketAddress(ip, port);
                    socket.connect(address, TIMEOUT);
                }
                os = socket.getOutputStream();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return os;
        }
        return os;
    }

    public static InputStream getIS() {
        if (is == null) {
            try {
                is = socket.getInputStream();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return is;
        }
        return is;
    }
}
